package cn.bugstack.mybatis.executor.statement;

import cn.bugstack.mybatis.executor.Executor;
import cn.bugstack.mybatis.executor.ParameterHandler;
import cn.bugstack.mybatis.executor.resultset.ResultSetHandler;
import cn.bugstack.mybatis.mapping.BoundSql;
import cn.bugstack.mybatis.mapping.MappedStatement;
import cn.bugstack.mybatis.session.Configuration;
import cn.bugstack.mybatis.session.ResultHandler;
import cn.bugstack.mybatis.session.RowBounds;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * statement处理器基类
 * @author xingshujing
 */
public abstract class BaseStatementHandler implements StatementHandler{

    protected final Executor executor;
    protected final RowBounds rowBounds;
    protected Configuration configuration;
    protected MappedStatement mappedStatement;

    protected Object parameterObject;

    protected final ParameterHandler parameterHandler;
    protected ResultSetHandler resultSetHandler;

    protected BoundSql boundSql;

    public BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
        this.configuration = mappedStatement.getConfiguration();
        this.executor = executor;
        this.mappedStatement = mappedStatement;
        this.rowBounds = rowBounds;
        if (boundSql == null) {
            boundSql = mappedStatement.getSqlSource().getBoundSql(parameterObject);
        }
        this.boundSql = boundSql;

        this.parameterObject = parameterObject;
        this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
        this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, resultHandler, boundSql);
    }

    @Override
    public Statement prepare(Connection connection) {
        Statement statement = null;

        try {
            statement = instantiateStatement(connection);
            statement.setQueryTimeout(350);
            statement.setFetchSize(10000);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return statement;
    }

    /**
     * statement分为3种
     * @param connection
     * @return
     */
    protected abstract Statement instantiateStatement(Connection connection) throws SQLException;
}
